package mz.behaveas.model.expectation {
	import mz.behaveas.model.ducktype.Duck;

	/**
	 * Creates an Expectation implementation from an anonymous object instance.
	 * //TODO make the keywords localizable
	 * 
	 * @author maxim.zaks@gmail.com
	 */
	public class ExpectationFactory {
		
		private static var DESC_KEYWORD : String = "description";
		private static var IGNORE_KEYWORD : String = "ignore";
		private static var BEHAVIOUR_KEYWORD : String = "behaviour";
		private static var SHOULD_EQ_KEYWORD : String = "shouldEqual";
		private static var SHOULD_NEQ_KEYWORD : String = "shouldNotEqual";
		private static var SHOULD_THROW_KEYWORD : String = "shouldThrow";
		
		public static function createExpectation(input : *) : Expectation {
			
			var desc : Boolean = false;
			var ign : Boolean = false;
			var beh : Boolean = false;
			var se : Boolean = false;
			var sne : Boolean = false;
			var st : Boolean = false;
			for (var memberName : String in input) {
				if(memberName == DESC_KEYWORD && (input[DESC_KEYWORD] is String)) {
					desc = true;
				}else if(memberName == IGNORE_KEYWORD) {
					if(!(input[IGNORE_KEYWORD] is String)) {
						return new MallformedExpectation(MallformedExpectationErrorText.IGNORE);
					}
					ign = true;
				}else if(memberName == BEHAVIOUR_KEYWORD) {
					if(!(input[BEHAVIOUR_KEYWORD] is Function)) {
						return new MallformedExpectation(MallformedExpectationErrorText.BEHAVIOUR);
					}
					beh = true;
				}else if(memberName == SHOULD_EQ_KEYWORD) {
					if(sne || st) {
						return new MallformedExpectation(MallformedExpectationErrorText.SHOULD);
					}
					se = true;
				}else if(memberName == SHOULD_NEQ_KEYWORD) {
					if(se || st) {
						return new MallformedExpectation(MallformedExpectationErrorText.SHOULD);
					}
					sne = true;
				}else if(memberName == SHOULD_THROW_KEYWORD) {
					if(sne || se) {
						return new MallformedExpectation(MallformedExpectationErrorText.SHOULD);
					}
					if(!(input[SHOULD_THROW_KEYWORD] is Class || input[SHOULD_THROW_KEYWORD] is Duck)) {
						return new MallformedExpectation(MallformedExpectationErrorText.SHOULD_THROW_VALUE);
					}
					st = true;
				}
			}
			
			if(!desc) {
				return new MallformedExpectation(MallformedExpectationErrorText.DESCRIPTION);
			}
			
			var description : String = input[DESC_KEYWORD] as String;
			
			if(ign) {
				var ignore : String = input[IGNORE_KEYWORD];
				return new IgnoredExpectation(description, ignore);
			}
			
			if(!beh) {
				return new NotImplementedExpectation(description);
			} else {
				if(!(se || sne || st)) {
					return new MallformedExpectation(MallformedExpectationErrorText.NO_SHOULD);
				}
			}
			
			if(se) {
				return new EqualExpectation(description, input[BEHAVIOUR_KEYWORD], input[SHOULD_EQ_KEYWORD]);
			}
			
			if(sne) {
				return new NotEqualExpectation(description, input[BEHAVIOUR_KEYWORD], input[SHOULD_NEQ_KEYWORD]);
			}
			
			if(st) {
				return new ThrowExpectation(description, input[BEHAVIOUR_KEYWORD], input[SHOULD_THROW_KEYWORD]);
			}
			
			return new MallformedExpectation(MallformedExpectationErrorText.UNKNOWN);
		}

	}
}
